/* 二维向量 */
class Vector2 extends Array{
	constructor(x=0, y=0){
		super(x, y);
	}
	
	get x(){
		return this[0];
	}
	set x(v){
		this[0] = v;
	}
	get y(){
		return this[1];
	}
	set y(v){
		this[1] = v;
	}
	
	set(x, y){
		this[0] = x,
		this[1] = y;
		return this;
	}
	setX(value){
		this[0] = value;
		return this;
	}
	setY(value){
		this[1] = value;
		return this;
	}
	
	
	//克隆
	clone(){
		return new this.constructor(...this);
	}
	
	//逐元素运算
	add(vec){
		this[0] += vec[0],
		this[1] += vec[1];
		return this;
	}
	
	sub(vec){
		this[0] -= vec[0],
		this[1] -= vec[1];
		return this;
	}
	
	multiple(vec){
		this[0] *= vec[0],
		this[1] *= vec[1];
		return this;
	}
	
	divideBy(vec){
		this[0] /= vec[0],
		this[1] /= vec[1];
		return this;
	}
	
	//点乘
	dot(vec){
		return this[0] * vec[0] +
			this[1] * vec[1];
	}
	
	//叉乘
	cross(vec){
		return new Vector3(
			0,
			0,
			this[0] * vec[1] - this[1] * vec[0]
		);
	}
	
	//向量运算
	addScale(scale){
		this[0] += scale,
		this[1] += scale;
		return this;
	}
	
	subScale(scale){
		this[0] -= scale,
		this[1] -= scale;
		return this;
	}
	
	multipleScale(scale){
		this[0] *= scale,
		this[1] *= scale;
		return this;
	}
	
	divideByScale(scale){
		this[0] /= scale,
		this[1] /= scale;
		return this;
	}
	
	//长度
	len(){
		return Math.sqrt(
			this[0] * this[0] +
			this[1] * this[1]
		);
	}
	
	lenSqr(){
		return this[0] * this[0] +
			this[1] * this[1];
	}
	
	normalize(){
		const len = this.len();
		this[0] /= len,
		this[1] /= len;
		return this;
	}
	
	//旋转
	rotate(rad){
		const x = this.x * Math.cos(rad) - this.y * Math.sin(rad),
			y = this.x * Math.sin(rad) + this.y * Math.cos(rad);
		this[0] = x,
		this[1] = y;
		return this;
	}
}



/* 三维向量 */
class Vector3 extends Array{
	constructor(x=0, y=0, z=0){
		super(x, y, z);
	}
	
	get x(){
		return this[0];
	}
	set x(v){
		this[0] = v;
	}
	get y(){
		return this[1];
	}
	set y(v){
		this[1] = v;
	}
	get z(){
		return this[2];
	}
	set z(v){
		this[2] = v;
	}
	
	get r(){
		return this[0];
	}
	set r(v){
		this[0] = v;
	}
	get g(){
		return this[1];
	}
	set g(v){
		this[1] = v;
	}
	get b(){
		return this[2];
	}
	set b(v){
		this[2] = v;
	}
	
	set(x, y, z){
		this[0] = x,
		this[1] = y;
		this[2] = z;
		return this;
	}
	setX(value){
		this[0] = value;
		return this;
	}
	setY(value){
		this[1] = value;
		return this;
	}
	setZ(value){
		this[2] = value;
		return this;
	}
	setR(value){
		this[0] = value;
		return this;
	}
	setG(value){
		this[1] = value;
		return this;
	}
	setB(value){
		this[2] = value;
		return this;
	}
	
	
	//克隆
	clone(){
		return new this.constructor(...this);
	}
	
	//逐元素运算
	add(vec){
		this[0] += vec[0],
		this[1] += vec[1],
		this[2] += vec[2];
		return this;
	}
	
	sub(vec){
		this[0] -= vec[0],
		this[1] -= vec[1],
		this[2] -= vec[2];
		return this;
	}
	
	multiple(vec){
		this[0] *= vec[0],
		this[1] *= vec[1],
		this[2] *= vec[2];
		return this;
	}
	
	divideBy(vec){
		this[0] /= vec[0],
		this[1] /= vec[1],
		this[2] /= vec[2];
		return this;
	}
	
	//点乘
	dot(vec){
		return this[0] * vec[0] +
			this[1] * vec[1] +
			this[2] * vec[2];
	}
	
	//叉乘
	cross(vec){
		return new this.constructor(
			this[1] * vec[2] - this[2] * vec[1],
			this[2] * vec[0] - this[0] * vec[2],
			this[0] * vec[1] - this[1] * vec[0]
		);
	}
	
	//向量运算
	addScale(scale){
		this[0] += scale,
		this[1] += scale,
		this[2] += scale;
		return this;
	}
	
	subScale(scale){
		this[0] -= scale,
		this[1] -= scale,
		this[2] -= scale;
		return this;
	}
	
	multipleScale(scale){
		this[0] *= scale,
		this[1] *= scale,
		this[2] *= scale;
		return this;
	}
	
	divideByScale(scale){
		this[0] /= scale,
		this[1] /= scale,
		this[2] /= scale;
		return this;
	}
	
	//长度
	len(){
		return Math.sqrt(
			this[0] * this[0] +
			this[1] * this[1] +
			this[2] * this[2]
		);
	}
	
	lenSqr(){
		return this[0] * this[0] +
			this[1] * this[1] +
			this[2] * this[2];
	}
	
	normalize(){
		const len = this.len();
		this[0] /= len,
		this[1] /= len,
		this[2] /= len;
		return this;
	}
	
	//旋转
	rotateX(rad){
		const y = this.y * Math.cos(rad) - this.z * Math.sin(rad),
			z = this.y * Math.sin(rad) + this.z * Math.cos(rad);
		this[1] = y,
		this[2] = z;
		return this;
	}
	
	rotateY(rad){
		const z = this.z * Math.cos(rad) - this.x * Math.sin(rad),
			x = this.z * Math.sin(rad) + this.x * Math.cos(rad);
		this[2] = z,
		this[0] = x;
		return this;
	}
	
	rotateZ(rad){
		const x = this.x * Math.cos(rad) - this.y * Math.sin(rad),
			y = this.x * Math.sin(rad) + this.y * Math.cos(rad);
		this[0] = x,
		this[1] = y;
		return this;
	}
}



/* 四维向量 */
class Vector4 extends Array{
	constructor(x=0, y=0, z=0, w=0){
		super(x, y, z, w);
	}
	
	
	get x(){
		return this[0];
	}
	set x(v){
		this[0] = v;
	}
	get y(){
		return this[1];
	}
	set y(v){
		this[1] = v;
	}
	get z(){
		return this[2];
	}
	set z(v){
		this[2] = v;
	}
	get w(){
		return this[3];
	}
	set w(v){
		this[3] = v;
	}
	
	get r(){
		return this[0];
	}
	set r(v){
		this[0] = v;
	}
	get g(){
		return this[1];
	}
	set g(v){
		this[1] = v;
	}
	get b(){
		return this[2];
	}
	set b(v){
		this[2] = v;
	}
	get a(){
		return this[3];
	}
	set a(v){
		this[3] = v;
	}
	
	
	set(x, y, z, w){
		this[0] = x,
		this[1] = y;
		this[2] = y;
		this[3] = w;
		return this;
	}
	setX(value){
		this[0] = value;
		return this;
	}
	setY(value){
		this[1] = value;
		return this;
	}
	setZ(value){
		this[2] = value;
		return this;
	}
	setW(value){
		this[3] = value;
		return this;
	}
	setR(value){
		this[0] = value;
		return this;
	}
	setG(value){
		this[1] = value;
		return this;
	}
	setB(value){
		this[2] = value;
		return this;
	}
	setA(value){
		this[3] = value;
		return this;
	}
	
	
	
	//克隆
	clone(){
		return new this.constructor(...this);
	}
	
	//逐元素运算
	add(vec){
		this[0] += vec[0],
		this[1] += vec[1],
		this[2] += vec[2],
		this[3] += vec[3];
		return this;
	}
	
	sub(vec){
		this[0] -= vec[0],
		this[1] -= vec[1],
		this[2] -= vec[2],
		this[3] -= vec[3];
		return this;
	}
	
	multiple(vec){
		this[0] *= vec[0],
		this[1] *= vec[1],
		this[2] *= vec[2],
		this[3] *= vec[3];
		return this;
	}
	
	divideBy(vec){
		this[0] /= vec[0],
		this[1] /= vec[1],
		this[2] /= vec[2],
		this[3] /= vec[3];
		return this;
	}
	
	//点乘
	dot(vec){
		return this[0] * vec[0] +
			this[1] * vec[1] +
			this[2] * vec[2] +
			this[3] * vec[3];
	}
	
	//向量运算
	addScale(scale){
		this[0] += scale,
		this[1] += scale,
		this[2] += scale,
		this[3] += scale;
		return this;
	}
	
	subScale(scale){
		this[0] -= scale,
		this[1] -= scale,
		this[2] -= scale,
		this[3] -= scale;
		return this;
	}
	
	multipleScale(scale){
		this[0] *= scale,
		this[1] *= scale,
		this[2] *= scale,
		this[3] *= scale;
		return this;
	}
	
	divideByScale(scale){
		this[0] /= scale,
		this[1] /= scale,
		this[2] /= scale,
		this[3] /= scale;
		return this;
	}
	
	//长度
	len(){
		return Math.sqrt(
			this[0] * this[0] +
			this[1] * this[1] +
			this[2] * this[2] +
			this[3] * this[3]
		);
	}
	
	lenSqr(){
		return this[0] * this[0] +
			this[1] * this[1] +
			this[2] * this[2] +
			this[3] * this[3];
	}
	
	normalize(){
		const len = this.len();
		this[0] /= len,
		this[1] /= len,
		this[2] /= len,
		this[3] /= len;
		return this;
	}
}